package com.lingyun.financialmanagement.service.pojo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.generator.IFill;
import com.lingyun.financialmanagement.dao.mapper.BillMapper;
import com.lingyun.financialmanagement.dao.mapper.ComponentPartMapper;
import com.lingyun.financialmanagement.dao.mapper.ProjectMapper;
import com.lingyun.financialmanagement.dao.mapper.UsersMapper;
import com.lingyun.financialmanagement.dao.pojo.*;
import com.lingyun.financialmanagement.service.ComponentPartService;
import com.lingyun.financialmanagement.utils.ProjectUtils;
import com.lingyun.financialmanagement.utils.TokenGetUser;
import com.lingyun.financialmanagement.vo.ComponentCredit;
import com.lingyun.financialmanagement.vo.ErrorCode;
import com.lingyun.financialmanagement.vo.Result;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


@Slf4j
@Service
public class ComponentPartServiceImpl implements ComponentPartService {

    @Autowired
    private ComponentPartMapper componentPartMapper;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${redis.token.tokenAccountPrefix}")
    private String tokenAccountPrefix;
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private ProjectServiceImpl projectServiceImpl;
    @Autowired
    private OperationLogServiceImpl operationLogServiceImpl;

    @Override
    public Result selectByProjectToComponent(Integer projectId) {
        if (projectId == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project", projectId);
        queryWrapper.ne("state", "删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    public Result selectAllComponent() {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("state", "删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    public Result selectComponentById(Integer id) {
        ComponentPart componentPart = componentPartMapper.selectById(id);
        return Result.success(componentPart);
    }

    @Override
    public Result selectAllPayMethodComponent() {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_method", "verify_pay");
        queryWrapper.ne("state", "删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    public Result selectPayMethodComponentToken() {
        // 通过token获取账号去查询
        String token = request.getHeader("token");
        if (token == null || token.isEmpty()) {
            return Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());
        }
        String account = redisTemplate.opsForValue().get(tokenAccountPrefix + token);
        Users users = usersMapper.selectByAccount(account);
        if (users == null) {
            return Result.fail(ErrorCode.USERS_NULL.getCode(), ErrorCode.USERS_NULL.getMsg());
        }

        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("users", users.getId());
        queryWrapper.eq("payment_method", "verify_pay");
        queryWrapper.ne("state", "删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    @Transactional
    public Result addComponentPart(ComponentPart componentPart) {
        // 验证唯一性
        String serialNumber = componentPart.getSerialNumber();
        ComponentPart componentPart1 = componentPartMapper.selectBySerialNumber(serialNumber);
        if (componentPart1 != null) {
            return Result.fail(ErrorCode.SERIAL_NUMBER_UNIQUE.getCode(), ErrorCode.SERIAL_NUMBER_UNIQUE.getMsg());
        }

        // 获取账号 设置操作用户
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();
        componentPart.setUsers(users.getId());
        componentPart.setUpdateUsers(users.getId());

        int insert = 0;
        try{
            insert = componentPartMapper.insert(componentPart);
        } catch (Exception e){
            e.printStackTrace();
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0){
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }
        // 对项目做修改
        try {
            // 增加项目成本
            ProjectUtils.addWarehouseCost(componentPart.getProject(),componentPart.getPaymentMethod(), componentPart.getCostFront(), projectMapper, componentPart.getBill(), billMapper);
            // 增加项目税额（减少）
            ProjectUtils.addWarehouseTax(componentPart, projectMapper, billMapper);
        } catch (Exception e) {
            throw new RuntimeException("增加价格错误");
        }

        // 增加日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, componentPart.getId(), null, componentPart.getProject(), "增加了设备", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }

        return Result.success(componentPart);
    }

    @Override
    @Transactional
    public Result outPutComponentPart(Integer id, Integer number, Integer projectId) {
    // 设置当前项目金钱减去
        ComponentPart componentPart = componentPartMapper.selectById(id);
        // 是否符合规则
        if (componentPart.getNumber() < number) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return Result.fail(ErrorCode.USERS_NULL.getCode(), ErrorCode.USERS_NULL.getMsg());
        }
        Users users = (Users)usersResult.getData();


        // 获取原项目
        Project project = projectMapper.selectById(componentPart.getProject());

        // 如果相等的情况  （直接修改旧的）
        if (componentPart.getNumber().equals(number)) {
            // 减去项目金额 (不扣税额)
            ProjectUtils.subtractComponents(componentPart, true, number, projectMapper, billMapper);
            // 将元器件转到目标项目
            componentPart.setProject(projectId);
            if (project.getType().equals("warehouse")){
                componentPart.setRemark(componentPart.getRemark() + "来源：仓库");
            }else {
                componentPart.setRemark(componentPart.getRemark() + "来源：" + project.getName());
            }
            // 设置目标项目金钱增加
            ProjectUtils.addProjectMoneyToTax(componentPart, true, number, projectMapper, billMapper, projectId);
        }

        // 拿一部分的情况  (创建新的修改旧的)
        else {
            // 减去项目金额 (不扣税额)
            ProjectUtils.subtractComponents(componentPart, false, number, projectMapper, billMapper);

            // 增加元件到新的项目， 修改老的元件
            addComponentPartIF(componentPart, project, number, users, projectId);

            // 设置目标项目金钱增加
            ProjectUtils.addProjectMoneyToTax(componentPart, false, number, projectMapper, billMapper, projectId);

        }
        
        // 获取目标仓库
        Project projectTarget = projectMapper.selectById(projectId);
        String projectName = projectTarget.getName();
        // 如果是公司就改成false    就代表未出库    （同时转回公司的目标仓库加税前的价格）
        if (projectName.equals("公司")){
            componentPart.setIsTax(false);
        }else{
            componentPart.setIsTax(true);
        }

        // 更新元器件
        int update = 0;
        try{
            update = componentPartMapper.updateById(componentPart);
        } catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        // 记录日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, componentPart.getId(), null, componentPart.getProject(), "元器件移动位置", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }
        return Result.success(true);
    }

    @Override
    public Result selectWarehouseName(String name) {
        // 查询仓库id
        Result result = projectServiceImpl.selectWarehouse();
        if (result.getCode() != 200){
            return result;
        }
        Project warehouse = (Project) result.getData();

        // 查询元器件通过名字
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project", warehouse.getId());
        queryWrapper.ne("state", "删除");
        queryWrapper.like("name",name);
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    public Result selectWarehouseNumber(String serialNumber) {
        // 查询仓库id
        Result result = projectServiceImpl.selectWarehouse();
        if (result.getCode() != 200){
            return result;
        }
        Project warehouse = (Project) result.getData();

        // 查询元器件通过编号
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project",warehouse.getId());
        queryWrapper.like("serial_number",serialNumber);
        queryWrapper.ne("state", "删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);

        System.out.println("搜索内容:" + serialNumber);
        System.out.println("结果:" + componentParts);

        return Result.success(componentParts);
    }

    @Override
    public Result selectCreditComponent() {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_method", "公司赊销");
        queryWrapper.eq("state", "启用");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        ArrayList<ComponentCredit> componentCredits = new ArrayList<>();
        for (int i = 0; i < componentParts.size(); i++) {
            Project project = projectMapper.selectById(componentParts.get(i).getProject());
            Users users = usersMapper.selectById(componentParts.get(i).getUsers());
            ComponentCredit componentCredit = new ComponentCredit(componentParts.get(i).getId(), componentParts.get(i).getSerialNumber(), componentParts.get(i).getName(), componentParts.get(i).getCostFront(), users.getName(), componentParts.get(i).getCompany(), project.getName(), componentParts.get(i).getPaymentMethod(), componentParts.get(i).getType(), componentParts.get(i).getRemark(), componentParts.get(i).getCreateTime());
            componentCredits.add(componentCredit);
        }
        return Result.success(componentCredits);
    }

    @Transactional
    @Override
    public Result updatePaymentMethod(ComponentPart componentPartRequest) {
        Integer id = componentPartRequest.getId();
        String paymentMethod = componentPartRequest.getPaymentMethod();
        // 验证数据准确性
        if (paymentMethod == null || paymentMethod.isEmpty()){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }

        UpdateWrapper<ComponentPart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("payment_method", paymentMethod);
        // 更新数据
        int update = 0;
        try{
            update = componentPartMapper.update(updateWrapper);
        }catch (Exception e){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        // 计算税后值修改
        ComponentPart componentPart = componentPartMapper.selectById(id);
        Integer billId = componentPart.getBill();
        Bill bill = billMapper.selectById(billId);
        Boolean isTax = componentPart.getIsTax();
        // 如果未作回库等操作就用原价扣除，如果做了，就扣除税后
        BigDecimal cost;
        System.out.println("是否被转走" + isTax);
        if (!isTax){
            cost = componentPart.getCostFront();
        }else{
            cost = componentPart.getCostFront().divide(new BigDecimal("1").add(bill.getTaxRate()),2,BigDecimal.ROUND_HALF_UP);
        }
        // 暂时修改
//        cost = cost.divide(new BigDecimal("1").add(bill.getTaxRate()),2,BigDecimal.ROUND_HALF_UP);

        // 获取要修改的项目
        Integer projectId = componentPart.getProject();
        Project project = projectMapper.selectById(projectId);

        // 判断是否为赊销账户如果是则操作
        if (componentPart.getPaymentMethod().equals("公司赊销")){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }

        System.out.println("划账金额" + cost);

        // 判断核销到公户还是现金
        project.setCredit(project.getCredit().subtract(cost));
        if ("核销-公户".equals(componentPartRequest.getPaymentMethod())){
            project.setPublicCost(project.getPublicCost().add(cost));
        }else if ("核销-现金".equals(componentPartRequest.getPaymentMethod())){
            project.setCashCost(project.getPublicCost().add(cost));
        }

        // 借贷项目结束
        if (project.getType().equals("loan")){
            project.setState("结束");
        }
        int projectUpdate = 0;
        try{
            projectUpdate = projectMapper.updateById(project);
        } catch (Exception e){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (projectUpdate == 0){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        return Result.success(true);
    }

    @Override
    public Result selectComponentPartCreditCost() {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_method", "公司赊销");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        BigDecimal sumCost = BigDecimal.valueOf(0);
        for (int i = 0; i < componentParts.size(); i++) {
            sumCost = sumCost.add(componentParts.get(i).getCostFront());
        }
        return Result.success(sumCost);
    }

    @Override
    public Result addBusinessTrip(BusinessTrip businessTrip) {
        String serialNumber = "差旅" + System.currentTimeMillis();
        Integer project = businessTrip.getProject();
        BigDecimal cost = businessTrip.getCost();
        String name = businessTrip.getName();
        Integer bill = businessTrip.getBill();
        String remark = businessTrip.getRemark();
        String paymentMethod = businessTrip.getPaymentMethod();

        // 获取用户id
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();

        // 插入
        ComponentPart componentPart = new ComponentPart(null, serialNumber, name, 1, cost, cost, bill, users.getId(), paymentMethod, null, project,null, "business", remark, null, users.getId(), null, null);
        int insert = 0;
        try{
            insert = componentPartMapper.insert(componentPart);
        } catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0) {
            throw new RuntimeException(ErrorCode.INSERT_ERROR.getMsg());
        }

        // 增加项目/仓库成本和税额
        try{
            ProjectUtils.addWarehouseCost(project, paymentMethod, cost, projectMapper, bill, billMapper);
            ProjectUtils.addWarehouseTax(componentPart, projectMapper, billMapper);
        } catch (Exception e){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        // 记录日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, componentPart.getId(), componentPart.getProject(), "提交了差旅表单", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }
        return Result.success(componentPart);
    }

    @Override
    @Transactional
    public Result deleteComponentById(Integer id) {
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();
        UpdateWrapper<ComponentPart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("state", "待删除");
        updateWrapper.set("update_users", users.getId());
        int update = 0;
        try {
            update = componentPartMapper.update(updateWrapper);
        }catch (Exception e){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }

        ComponentPart componentPart = componentPartMapper.selectById(id);

        try{
            // 删除项目资金
            ProjectUtils.subtractComponents(componentPart, projectMapper);
            // 删除项目税额
            ProjectUtils.subtractWarehouseTax(componentPart, projectMapper, billMapper);

        }catch (Exception e){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        return Result.success(true);
    }

    @Override
    public Result selectCheckPending() {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", "待删除");
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    @Transactional
    public Result updateCheckPending(Integer id, String state) {
        if (!("启用".equals(state) || "删除".equals(state))){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        UpdateWrapper<ComponentPart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("state", state);
        // 更新
        int update = 0;
        try{
            update = componentPartMapper.update(updateWrapper);
        }catch (Exception e){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            throw new RuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }

        return Result.success(true);
    }

    @Override
    public Result selectReviewComponentByToken() {
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", "待删除").and( q -> {
                    q.eq("update_users", users.getId()).or()
                    .eq("users", users.getId());
        });

        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        return Result.success(componentParts);
    }

    @Override
    public Result revocationComponentState(Integer id) {
        UpdateWrapper<ComponentPart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("state", "启用");

        int update = 0;
        try{
            update = componentPartMapper.update(updateWrapper);
        } catch (Exception e){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }
        return Result.success(true);
    }

    // 如果拿取的数据为一部分，则新建同时修改老的
    public void addComponentPartIF(ComponentPart componentPart, Project project, Integer number, Users users, Integer projectId) {
        // 设置编号
        String serialNumber = componentPart.getSerialNumber() + "-分支-" + new Random().nextInt(10000)+1;
        // 新对象 税前花费金额
        BigDecimal newCostFront = componentPart.getCostFront().divide(new BigDecimal(componentPart.getNumber()), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(number));
        String remark = null;
        if (project.getType().equals("warehouse")){
            remark = componentPart.getRemark() + "来源：仓库";
        }else {
            remark = componentPart.getRemark() + "来源：" + project.getName();
        }
        ComponentPart componentPartNew = new ComponentPart(null, serialNumber, componentPart.getName(), number, componentPart.getUnitPrice(), newCostFront, componentPart.getBill(), componentPart.getUsers(), componentPart.getPaymentMethod(), componentPart.getCompany(), projectId,null, componentPart.getType(), remark,null, users.getId(), componentPart.getCreateTime(), null);

        // 减掉上一个的数量,还有税前花费金额
        // 税前金额修改
        componentPart.setCostFront(componentPart.getCostFront().subtract(newCostFront));
        // 减去数量
        componentPart.setNumber(componentPart.getNumber() - number);
        // 更改修改人
        componentPartNew.setUpdateUsers(users.getId());

        // 插入新项目
        int insert = 0;
        try{
            insert = componentPartMapper.insert(componentPartNew);
        } catch (Exception e){
            throw new RuntimeException(ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0){
            throw new RuntimeException(ErrorCode.INSERT_ERROR.getMsg());
        }
    }
}
